import uuid
from datetime import datetime
from dateutil.relativedelta import relativedelta
from appAccounts.models.db import engine
from appAccounts.models.models import mAccount
from sqlalchemy import text
from sqlalchemy.orm import sessionmaker
from fastapi import HTTPException, status
from appAccounts.utils.ftg_utils import is_feature_enabled
from appAccounts.services.serviceCustomerWS import do_check_customer
from appAccounts.utils.log_utils import logger

async def create_account(aToken: str, newaccount: mAccount)->HTTPException:
    logger.info("======================")
    logger.info(newaccount)
    logger.info("======================")

    acc_dict = newaccount.dict()

    session = sessionmaker(bind=engine)
    mysession = session()
    new_account = mAccount(**acc_dict)

    check_feature = is_feature_enabled("customer_validation")
    logger.info(f"customer_validation feature in use is {check_feature}")

    if check_feature:
        logger.info(f"customer_validation feature in use is {check_feature}")
        if not do_check_customer(str(newaccount.cust_id), aToken):
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Operation is prohibited")

    logger.info("start to create new customer")
    pool_size = engine.pool.checkedout()
    logger.info(f"Current pool size usage: {pool_size}")

    next_acc_number = mysession.execute(text("SELECT nextval('app_accounts.account_id_gen')")).fetchone()[0]
    logger.info(f"Next acc value is: {next_acc_number}")

    new_account.id = uuid.uuid4()
    new_account.account_number = f"{new_account.currency.title().upper()}{str(new_account.duration_months).zfill(3)}{str(next_acc_number).zfill(8)}"
    acc_end_date = datetime.now()+relativedelta(months=new_account.duration_months)
    new_account.end_date = acc_end_date.date()

    mysession.add(new_account)
    mysession.commit()

    logger.info("done")
    pool_size = engine.pool.checkedout()
    logger.info(f"Current pool size usage: {pool_size}")
    return {"acc_id":new_account.id, "acc_num": new_account.account_number, "end_date": new_account.end_date}

async def close_account(aToken: str, closeaccount: mAccount)->HTTPException:
    logger.info("======================")
    logger.info(close_account)
    logger.info("======================")

    acc_dict = closeaccount.dict()

    session = sessionmaker(bind=engine)
    mysession = session()

    check_feature = is_feature_enabled("customer_validation")
    logger.info(f"customer_validation feature in use is {check_feature}")

    account_to_del = mysession.query(mAccount).filter(mAccount.id==closeaccount.id,
                                                     mAccount.cust_id==closeaccount.cust_id,
                                                     mAccount.is_active == True
                                                     ).first()
    if account_to_del is not None:
        if check_feature:
            logger.info(f"customer_validation feature in use is {check_feature}")
            if not do_check_customer(str(account_to_del.cust_id), aToken):
                raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Operation is prohibited")

        account_to_del.is_active = False
        mysession.commit()
        logger.info(f"done account {account_to_del.account_number} was deleted")
    else:
        logger.error("no such account for deletion")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="No such account")

    return {"id": account_to_del.id, "is_active": account_to_del.is_active}


async def modify_account(aToken: str, updaccount: mAccount)->HTTPException:
    logger.info("======================")
    logger.info(modify_account)
    logger.info("======================")

    acc_dict = updaccount.dict()

    session = sessionmaker(bind=engine)
    mysession = session()

    check_feature = is_feature_enabled("customer_validation")
    logger.info(f"customer_validation feature in use is {check_feature}")

    account_to_upd = mysession.query(mAccount).filter(mAccount.id==updaccount.id,
                                                      mAccount.cust_id==updaccount.cust_id,
                                                      mAccount.currency==updaccount.currency,
                                                      mAccount.is_active == True
                                                      ).first()
    if account_to_upd is not None:
        if check_feature:
            logger.info(f"customer_validation feature in use is {check_feature}")
            if not do_check_customer(str(account_to_upd.cust_id), aToken):
                raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Operation is prohibited")

        if updaccount.top_up_amnt is not None:
            account_to_upd.amount = account_to_upd.amount + updaccount.top_up_amnt
            if updaccount.withdraw_amnt is not None and account_to_upd.amount >= updaccount.withdraw_amnt:
                account_to_upd.amount = account_to_upd.amount - updaccount.withdraw_amnt
            else:
                logger.error("Not enough money at account")
                raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Not enough money on account")

        mysession.commit()
        logger.info(f"done account {account_to_upd.id} was modified")
    else:
        logger.error("no such account for deletion")
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="No such account")

    return {"id": account_to_upd.id, "is_active": account_to_upd.is_active, "new amount": account_to_upd.amount}

async def get_all_accounts(aToken: str, getaccounts: mAccount)->HTTPException:
    logger.info("======================")
    logger.info(get_all_accounts)
    logger.info("======================")

    acc_dict = getaccounts.dict()

    session = sessionmaker(bind=engine)
    mysession = session()

    check_feature = is_feature_enabled("customer_validation")
    logger.info(f"customer_validation feature in use is {check_feature}")

    if check_feature:
        logger.info(f"customer_validation feature in use is {check_feature}")
        if not do_check_customer(str(getaccounts.cust_id), aToken):
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Operation is prohibited")

    accounts_list = mysession.query(mAccount).filter(mAccount.cust_id==getaccounts.cust_id,
                                                     mAccount.is_active == True
                                                    ).all()
    if accounts_list is not None:
        return accounts_list
    else:
        return {}
